package com.wing.user.controller.app;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wing.common.constant.ClientId;
import com.wing.common.utils.JsonResult;
import com.wing.common.utils.PageResult;
import com.wing.common.utils.RSAUtils;
import com.wing.oauth2.feign.LoginFeignClient;
import com.wing.user.config.WxMaConfiguration;
import com.wing.user.model.entity.*;
import com.wing.user.model.request.WxUserForm;
import com.wing.user.service.*;
import com.wing.web.utils.JwtUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import mode.TokenVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * app-用户管理
 */
@Slf4j
@Validated
@Api(value = "app-用户管理", tags = "#/user/user")
@RestController
@RequestMapping("/user/app/user")
@RequiredArgsConstructor
public class UserAppController {

    @Autowired
    private UserService userService;


    @Value("${oauth2.appName}")
    private String appName;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private LoginFeignClient loginFeignClient;

    private final PasswordEncoder passwordEncoder;

    private final DepartmentService departmentService;
    private final CompanyInfoService companyInfoService;
    private final RoleService roleService;
    private final UserRoleService userRoleService;
    private final RoleMenuService roleMenuService;

    private static Long departmentId = null;

    @ApiOperation(value = "查询所有用户", notes = "搜索")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "第几页", example = "1", required = true,  dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "limit", value = "每页多少条", example = "10", required = true, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "searchKey", value = "筛选条件字段", example = "phone", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "searchValue", value = "筛选条件关键字", example = "13888888888", dataType = "String", paramType = "query")
    })
    @GetMapping("/listAll")
    public PageResult<User> listAll(Integer page, Integer limit, String searchKey, String searchValue,
                                 Long departmentId, Long postId, String username, String nickname, String phone, String idCard) {
        if (page == null) {
            page = 1;
        }
        if (limit == null) {
            limit = 10;
        }
        Page<User> userPage = new Page<>(page, limit);
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.ne("id",519906343969112064l);
        if (searchKey != null && !searchKey.trim().isEmpty() && searchValue != null && !searchValue.trim().isEmpty()) {
            wrapper.eq(searchKey, searchValue);
        }
        wrapper.orderBy(true, false,"create_time");
        if(null != departmentId){
            wrapper.eq("department_id", departmentId);
        }
        if(null != postId){
            wrapper.eq("post_id", postId);
        }
        if(StringUtils.isNotBlank(username)){
            wrapper.like("username", "%"+username+"%");
        }
        if(StringUtils.isNotBlank(nickname)){
            wrapper.like("nickname", "%"+nickname+"%");
        }
        if(StringUtils.isNotBlank(phone)){
            wrapper.like("phone", "%"+phone+"%");
        }
        if(StringUtils.isNotBlank(idCard)){
            wrapper.like("id_card", "%"+idCard+"%");
        }
        Map paramMap=new HashMap();
        paramMap.put("departmentId",departmentId);
        paramMap.put("postId",postId);
        paramMap.put("username",username);
        paramMap.put("nickname",nickname);
        paramMap.put("phone",phone);
        paramMap.put("idCard",idCard);
        this.departmentId = JwtUtils.getEnterpriseId();
        Page<User> pageList=userService.pageList(userPage, paramMap);
//        List<User> userList = userPage.getRecords();
        List<User> userList = pageList.getRecords();
        if(userList.size() > 0){
            // 关联查询role
            List<Long> userIds = new ArrayList<>();
            for (User one : userList) {
                userIds.add(one.getId());
            }
            List<UserRole> userRoles = userRoleService.list(new QueryWrapper<UserRole>().in("user_id", userIds));
            List<Role> roles = roleService.list(null);
            for (User one : userList) {
                List<Role> tempUrs = new ArrayList<>();
                for (UserRole ur : userRoles) {
                    if (one.getId().equals(ur.getUserId())) {
                        for (Role r : roles) {
                            if (ur.getRoleId().equals(r.getId())) {
                                tempUrs.add(r);
                            }
                        }
                    }
                }

                one.setRoles(tempUrs);
            }
        }
        //关联相关业务属性
//        userList.parallelStream().forEach(k -> {
//            log.info("关联相关业务属性查询开始: companyInfoId = " + k.getCompanyInfoId());
//            // 企业
//            CompanyInfo companyInfo = companyInfoService.getById(k.getCompanyInfoId());
//            if(companyInfo != null){
//                k.setCompanyInfoName(companyInfo.getName());
//            }
//
//            log.info("关联相关业务属性查询开始: departmentId = " + k.getDepartmentId());
//            // 部门
//            Department department = departmentService.getById(k.getDepartmentId());
//            if(department != null){
//                k.setDepartmentName(department.getName());
//            }
//        });
        return new PageResult<>(userList, pageList.getTotal());
    }


    /**
     * 获取当前登录用户信息
     */
    @GetMapping("/getUser")
    public JsonResult<User> getUser() {
        Long userId = JwtUtils.getLoginUserId();
        User one = userService.getByUserId(userId);
        return JsonResult.success(one);
    }

    /**
     * 小程序查询所有用户
     */
    @GetMapping("/listApplet")
    public JsonResult listApplet(){
        List<User> list = userService.list();
        return JsonResult.success(list);
    }

    /**
     * 手机号登录
     *
     * @param code    验证码
     */
    @PostMapping("/loginByPhone")
    public JsonResult<Object> login(@RequestParam("phone") String phone, @RequestParam("code") String code) {

        //判断手机号是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //用户名即是手机号
        queryWrapper.eq("phone", phone);
        User user = userService.getOne(queryWrapper);
        //获取验证码
        String phoneCode = redisTemplate.opsForValue().get("SMS_CODE:"+phone);
        if (!code.equals(phoneCode)) {
            return JsonResult.fail("验证码不一致!");
        }
        if (user != null) {
            JSONObject jsonObject = userService.findByUserId(user.getId(), ClientId.CLIENT_ID_WX,ClientId.CLIENT_ID_WX,null,null,null);
//                JsonResult<TokenVO> jsonResult=loginFeignClient.login(user.getUsername(),user.getPassword(),"password","webApp","webApp");
                return JSONObject.parseObject(jsonObject.toString(),JsonResult.class);
        } else {
            return JsonResult.fail("手机号不存在!");
        }
    }

    public JsonResult<Object> login(@RequestParam("phone") String phone) {

        //判断手机号是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //用户名即是手机号
        queryWrapper.eq("phone", phone);
        User user = userService.getOne(queryWrapper);
        //获取验证码
        String phoneCode = redisTemplate.opsForValue().get("SMS_CODE:"+phone);
//        phoneCode = "6666";

        if (user != null) {
//            JsonResult<TokenVO> jsonResult=loginFeignClient.login(user.getUsername(),user.getPassword(),"password","webApp","webApp");
//            return JsonResult.success("登录成功",jsonResult.getData());
            JSONObject jsonObject = userService.findByUserId(user.getId(), ClientId.CLIENT_ID_WX,ClientId.CLIENT_ID_WX,null,null,null);
            return JSONObject.parseObject(jsonObject.toString(),JsonResult.class);

        } else {
            return JsonResult.fail("手机号不存在!");
//            throw new BusinessException("手机号不存在!");
        }
    }

    /**
     * 授权登录
     * @param phone
     * @param openId
     * @return
     */
    @GetMapping("authorization")
    public JsonResult<TokenVO> authorization(@RequestParam("phone") String phone,@RequestParam("openId") String openId){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        User user = userService.getOne(queryWrapper);
        if(user == null){
            return JsonResult.fail("用户不存在！！！");
        }
        user.setOpenId(openId);
        userService.updateById(user);
        JsonResult<Object> jsonResult = this.login(phone);
        return JsonResult.success(jsonResult.getData());
    }

    @ApiOperation("小程序手机号登录")
    @PostMapping(value = "/weChatLogin")
    @SneakyThrows(WxErrorException.class)
    public JsonResult<TokenVO> getWxInfoThere(WxUserForm wxUserForm) {
        final WxMaService wxService = WxMaConfiguration.getMaService(wxUserForm.getAppId());
        log.info("参数=>{}",wxUserForm);
        WxMaJscode2SessionResult wx = wxService.jsCode2SessionInfo(wxUserForm.getCode());
        log.info("请求微信授权完成=>{}",wx);
        WxMaPhoneNumberInfo phoneInfo = wxService.getUserService().getPhoneNoInfo(wx.getSessionKey(), wxUserForm.getEncryptedData(), wxUserForm.getIv());
        log.info("获取手机号码完成=>{}",phoneInfo);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phoneInfo.getPhoneNumber());
        User user = userService.getOne(queryWrapper);
        if(user == null){
            return JsonResult.fail("用户不存在！！！");
        }
        user.setOpenId(wx.getOpenid());
        userService.updateById(user);
        JsonResult<Object> jsonResult = this.login(phoneInfo.getPhoneNumber());
        return JsonResult.success(jsonResult.getData());
    }

    @ApiOperation("弹簧柜/小柜子(不带面板)小程序手机号登录")
    @PostMapping(value = "/xgzWeChatLogin")
    @SneakyThrows(WxErrorException.class)
    public JsonResult<TokenVO> xgzWeChatLogin(WxUserForm wxUserForm) {
        final WxMaService wxService = WxMaConfiguration.getMaService(wxUserForm.getAppId());
        log.info("弹簧柜/小柜子(不带面板)小程序手机号登录，参数=>{}",wxUserForm);
        WxMaJscode2SessionResult wx = wxService.jsCode2SessionInfo(wxUserForm.getCode());
        log.info("弹簧柜/小柜子(不带面板)小程序手机号登录，请求微信授权完成=>{}",wx);
        WxMaPhoneNumberInfo phoneInfo = wxService.getUserService().getPhoneNoInfo(wx.getSessionKey(), wxUserForm.getEncryptedData(), wxUserForm.getIv());
        log.info("弹簧柜/小柜子(不带面板)小程序手机号登录，获取手机号码完成=>{}",phoneInfo);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phoneInfo.getPhoneNumber());
        User user = userService.getOne(queryWrapper);
        if(user == null){
            return JsonResult.fail("弹簧柜/小柜子(不带面板)小程序手机号登录，用户不存在！！！");
        }
        user.setOpenId(wx.getOpenid());
        userService.updateById(user);
        JsonResult<Object> jsonResult = this.login(phoneInfo.getPhoneNumber());
        return JsonResult.success(jsonResult.getData());
    }

    @ApiOperation("手机号获取token")
    @GetMapping("/getTokenByPhone")
    public JsonResult getTokenByPhone(@RequestParam("phone") String phone){
        JsonResult<Object> jsonResult = this.login(phone);
        if (jsonResult.getCode() == 200 ){
            return JsonResult.success(jsonResult.getData());
        }
        return JsonResult.fail(jsonResult.getMsg());
    }

    @ApiOperation("获取用户数据(柜机)")
    @GetMapping("/list")
    public JsonResult list(){
        List<User> list=userService.list(new QueryWrapper<User>().select("id,username,phone,nickname,header_img,face_data"));
        return JsonResult.success(list);
    }

    @ApiOperation("添加人脸")
    @PostMapping("/addHeaderImg")
    public JsonResult addHeaderImg(@RequestBody User user){
        user.setId(JwtUtils.getLoginUserId());
        JsonResult jsonResult=userService.addUserHeader(user);
        return jsonResult;
    }

    @ApiOperation("统计用户")
    @GetMapping("/statUsers")
    public JsonResult statUser(){
        Map resultMap=new HashMap();
        User user=userService.getByUserId(JwtUtils.getLoginUserId());
        resultMap.put("hasHeaderImg",(user==null||StringUtils.isNotBlank(user.getFaceData()))?true:false);
        resultMap.put("userQuantity",userService.count());
        return JsonResult.success(resultMap);
    }

    @ApiOperation("添加人脸特征数据")
    @PostMapping("/addFaceData")
    public JsonResult addFaceData(@RequestBody User user){
        userService.addFaceData(user);
        return JsonResult.success();
    }

    @ApiOperation(value = "修改自己密码", notes = "修改自己密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "oldPwd", value = "原密码", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "newPwd", value = "新密码", required = true, dataType = "String", paramType = "form")
    })
    @PostMapping("/updatePwd")
    public JsonResult updatePassword(@RequestBody User userInfo) {
        User user = userService.getById(JwtUtils.getLoginUserId());
        if (!passwordEncoder.matches(userInfo.getOldPwd(), user.getPassword())){
            return JsonResult.fail("原密码不正确");
        }
        User updateUser=new User();
        updateUser.setPassword(passwordEncoder.encode(userInfo.getNewPwd()));
        updateUser.setId(user.getId());
        updateUser.setIsUpdatePwd(true);
        try{
            String passwordRsa = RSAUtils.encryptByPublicKey(RSAUtils.publicKey, userInfo.getNewPwd());
            updateUser.setPasswordRsa(passwordRsa);
        }catch (Exception e){
            log.error("encrypt fail",e);
        }


        if (userService.updateById(updateUser)) {
            return JsonResult.success("修改成功");
        }
        return JsonResult.fail("修改失败");
    }


    /**
     * 对外开放的API接口列表(用户)
     * @param page
     * @param limit
     * @param departmentId
     * @param postId
     * @param username
     * @param nickname
     * @param phone
     * @return
     */
    @GetMapping("/foreignUserListAll")
    public PageResult<User> foreignUserListAll(Integer page, Integer limit,
                                    Long departmentId, Long postId, String username, String nickname, String phone) {
        if (page == null) {
            page = 1;
        }
        if (limit == null) {
            limit = 10;
        }
        Page<User> userPage = new Page<>(page, limit);
        Map paramMap=new HashMap();
        paramMap.put("departmentId",departmentId);
        paramMap.put("postId",postId);
        paramMap.put("username",username);
        paramMap.put("nickname",nickname);
        paramMap.put("phone",phone);
        Page<User> pageList=userService.pageList(userPage, paramMap);
        List<User> userList = pageList.getRecords();
        for(User user : userList){
            user.setPassword(null);
            user.setPasswordRsa(null);
            user.setFaceData(null);
        }
        return new PageResult<>(userList, pageList.getTotal());
    }

    /**
     * 对外开放的API接口详情(用户)
     * @param id
     * @return
     */
    @GetMapping("/foreignUserDetail")
    public JsonResult foreignUserDetail(Long id) {
        User user=userService.getById(id);
        if(null != user) {
            user.setPassword(null);
            user.setPasswordRsa(null);
            user.setFaceData(null);
        }
        return JsonResult.success(user);
    }

    /**
     * 对外开放的API接口列表(角色)
     * @param page
     * @param limit
     * @param departmentId
     * @param roleName
     * @return
     */
    @GetMapping("/foreignRoleListAll")
    public PageResult<Role> foreignRoleListAll(Integer page, Integer limit,
                                               Long departmentId, String roleName) {
        if (page == null) {
            page = 1;
        }
        if (limit == null) {
            limit = 10;
        }
        Page<Role> userPage = new Page<>(page, limit);
        Map paramMap=new HashMap();
        paramMap.put("departmentId",departmentId);
        paramMap.put("name",roleName);
        Page<Role> pageList=roleService.pageList4app(userPage, paramMap);
        List<Role> userList = pageList.getRecords();
        return new PageResult<>(userList, pageList.getTotal());
    }

    /**
     * 对外开放的API接口详情(角色)
     * @param id
     * @return
     */
    @GetMapping("/foreignRoleDetail")
    public JsonResult foreignRoleDetail(Long id) {
        Role role = roleService.getById(id);
        return JsonResult.success(role);
    }

    /**
     * 对外开放的API接口列表(部门)
     * @param page
     * @param limit
     * @param name
     * @return
     */
    @GetMapping("/foreignDepartmentListAll")
    public PageResult<Department> foreignDepartmentListAll(Integer page, Integer limit,
                                                           String name) {
        if (page == null) {
            page = 1;
        }
        if (limit == null) {
            limit = 10;
        }
        Page<Department> departmentPage = new Page<>(page, limit);
        Map paramMap=new HashMap();
        paramMap.put("name",name);
        Page<Department> pageList = departmentService.pageList4app(departmentPage, paramMap);
        List<Department> userList = pageList.getRecords();
        return new PageResult<>(userList, pageList.getTotal());
    }

    /**
     * 对外开放的API接口详情(部门)
     * @param id
     * @return
     */
    @GetMapping("/foreignDepartmentDetail")
    public JsonResult foreignDepartmentDetail(Long id) {
        Department department = departmentService.getById(id);
        return JsonResult.success(department);
    }

    /**
     * 对外开放的API接口列表(公司)
     * @param page
     * @param limit
     * @param name
     * @return
     */
    @GetMapping("/foreignCompanyInfoListAll")
    public PageResult<CompanyInfo> foreignCompanyInfoListAll(Integer page, Integer limit,
                                                         String name) {
        if (page == null) {
            page = 1;
        }
        if (limit == null) {
            limit = 10;
        }
        Page<CompanyInfo> companyInfoPage = new Page<>(page, limit);
        Map paramMap=new HashMap();
        paramMap.put("name",name);
        Page<CompanyInfo> pageList = companyInfoService.pageList4app(companyInfoPage, paramMap);
        List<CompanyInfo> userList = pageList.getRecords();
        return new PageResult<>(userList, pageList.getTotal());
    }

    /**
     * 对外开放的API接口详情(公司)
     * @param id
     * @return
     */
    @GetMapping("/foreignCompanyInfoDetail")
    public JsonResult foreignCompanyInfoDetail(Long id) {
        CompanyInfo companyInfo = companyInfoService.getById(id);
        return JsonResult.success(companyInfo);
    }

}
